package com.ke.forum.forumapi.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ke.forum.common.common.RedisKey;
import com.ke.forum.common.common.Result;
import com.ke.forum.common.common.ResultCode;
import com.ke.forum.common.utils.CommonUtils;
import com.ke.forum.forumapi.service.UserService;
import com.ke.forum.mbg.dao.ArticleMapper;
import com.ke.forum.mbg.dao.UserFollowMapper;
import com.ke.forum.mbg.entity.User;
import com.ke.forum.mbg.dao.UserMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ke.forum.mbg.entity.UserFollow;
import com.ke.forum.mbg.entity.dto.UserDto;
import com.ke.forum.mbg.mapstruct.UserMapstruct;
import com.ke.forum.shiro.config.shiro.JWTToken;
import com.ke.forum.shiro.exception.CustomException;
import com.ke.forum.shiro.utils.JWTUtils;
import com.ke.forum.shiro.utils.MD5Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 珂
 * @since 2021-05-22
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    UserMapper userMapper;
    @Autowired
    CommonUtils commonUtils;
    @Autowired
    RedisTemplate<String,Object> redisTemplate;
    @Autowired
    ArticleMapper articleMapper;
    @Autowired
    UserFollowMapper followMapper;

    @Override
    public Result signUp(User user) {
        User queryUser = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getEmail,user.getEmail()));
        if (queryUser!=null){
            return Result.FAIL("该邮箱已被注册");
        }
        JSONObject result = new JSONObject();
        String uuid = UUID.randomUUID().toString();
        user.setUuid(uuid);
        String randomUsername = "用户"+commonUtils.getStringRandom(8);
        user.setUsername(randomUsername);
        user.setGender("保密");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        String target = MD5Utils.md5Encryption(user.getPassword(),user.getEmail());
        user.setPassword(target);
        userMapper.insert(user);
        String token = JWTUtils.sign(user.getEmail(),target);
        result.put("token",token);
        return Result.SUCCESS(result);
    }

    @Override
    public Result login(User user) {
        Subject subject = SecurityUtils.getSubject();
        String target = MD5Utils.md5Encryption(user.getPassword(), user.getEmail());
        String token = JWTUtils.sign(user.getEmail(),JWTUtils.secret);
        User user1 = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getEmail, user.getEmail()));
        if (!target.equals("") && !target.equals(user1.getPassword())) {
            throw new CustomException(ResultCode.USER_LOGIN_ERROR);
        }
        subject.login(new JWTToken(token,target));
        UserDto userDto = (UserDto) SecurityUtils.getSubject().getPrincipal();
        redisTemplate.opsForValue().set(RedisKey.TOKEN_KEY+userDto.getToken(),userDto,2, TimeUnit.HOURS);
        userDto.setPassword(null);
        userDto.setId(null);
        userDto.setToken(token);
        //保存到redis内，下次跳过验证
        return Result.SUCCESS(userDto);
    }

    @Override
    public Result getUserInfo(String uuid, Boolean refresh) {
        UserDto userDto = (UserDto) SecurityUtils.getSubject().getPrincipal();
        //如果是获取自己的信息且刷新自己的token
        if(uuid==null&&refresh){
            redisTemplate.delete(RedisKey.TOKEN_KEY+userDto.getToken());
            Subject subject = SecurityUtils.getSubject();
            String token = JWTUtils.sign(userDto.getEmail(),JWTUtils.secret);
            subject.login(new JWTToken(token,userDto.getPassword()));
            redisTemplate.opsForValue().set(RedisKey.TOKEN_KEY+userDto.getToken(),userDto,2, TimeUnit.HOURS);
            userDto.setPassword(null);
            userDto.setId(null);
            userDto.setToken(token);
            return getResult(userDto);
            //获取自己的信息不刷新token
        }else if (uuid==null){
            userDto.setPassword(null);
            userDto.setId(null);
            //获取他人的信息
            return getResult(userDto);
        }else {
            User user = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUuid, uuid));
            user.setPassword(null);
            user.setTelephone(null);
            user.setId(null);
            user.setUpdateTime(null);
            user.setUpdateTime(null);
            user.setEmail(null);
            UserDto otherUserDto = UserMapstruct.INSTANCE.toDto(user);
            Integer articleNum = articleMapper.getUserArticleNum(uuid);
            Integer starNum = followMapper.selectCount(Wrappers.<UserFollow>lambdaQuery().eq(UserFollow::getUserUuid,uuid));
            Integer fanNum = followMapper.selectCount(Wrappers.<UserFollow>lambdaQuery().eq(UserFollow::getUpUuid,uuid));
            UserFollow userFollow = followMapper.selectOne(Wrappers.<UserFollow>lambdaQuery().eq(UserFollow::getUpUuid, uuid).eq(UserFollow::getUserUuid, userDto.getUuid()));
            otherUserDto.setIsStar(userFollow != null);
            otherUserDto.setArticleNum(articleNum);
            otherUserDto.setStarNum(starNum);
            otherUserDto.setFanNum(fanNum);
            return Result.SUCCESS(otherUserDto);
        }
    }

    private Result getResult(UserDto userDto) {
        Integer starNum = followMapper.selectCount(Wrappers.<UserFollow>lambdaQuery().eq(UserFollow::getUserUuid,userDto.getUuid()));
        Integer fanNum = followMapper.selectCount(Wrappers.<UserFollow>lambdaQuery().eq(UserFollow::getUpUuid,userDto.getUuid()));
        Integer articleNum = articleMapper.getUserArticleNum(userDto.getUuid());
        userDto.setArticleNum(articleNum);
        userDto.setStarNum(starNum);
        userDto.setFanNum(fanNum);
        return Result.SUCCESS(userDto);
    }

    @Override
    public Result updateUserInfo(User user) {
        UserDto userDto = (UserDto) SecurityUtils.getSubject().getPrincipal();
        if (!user.getUuid().equals(userDto.getUuid())){
            return Result.FAIL("不能修改他人的信息");
        }
        user.setId(userDto.getId());
        user.setEmail(userDto.getEmail());
        user.setUpdateTime(LocalDateTime.now());
        user.setPassword(userDto.getPassword());
        userMapper.updateById(user);
        User user1 = userMapper.selectById(user.getId());
        user1.setPassword(null);
        user1.setId(null);
        user1.setUpdateTime(null);
        user1.setUpdateTime(null);
        UserDto userDto1 = UserMapstruct.INSTANCE.toDto(user);
        return Result.SUCCESS(userDto1);
    }

    @Override
    public Result listStarUserInfo(Integer current) {
        Page<UserDto> page = new Page<>();
        page.setSize(10);
        page.setCurrent(current);
        UserDto userDto = (UserDto) SecurityUtils.getSubject().getPrincipal();
        Page<UserDto> userDtoPage = userMapper.listStarUserInfo(page, userDto.getUuid());
        return Result.SUCCESS(userDtoPage);
    }

    @Override
    public Result listFanUserInfo(Integer current) {
        Page<UserDto> page = new Page<>();
        page.setSize(10);
        page.setCurrent(current);
        UserDto userDto = (UserDto) SecurityUtils.getSubject().getPrincipal();
        Page<UserDto> userDtoPage = userMapper.listFanUserInfo(page, userDto.getUuid());
        return Result.SUCCESS(userDtoPage);
    }
}
